Scenario

Imagine you are a data scientist at a respected media outlet – say the “New York Times”. Your editor wants to support the writing of a feature article about How Couples Meet and Stay Together. Your editor-in-chief asks you to analyze some data from an extensive survey conducted by a researcher at Stanford University.

Since there is no way that all features of the data can be represented in such a memo, feel free to pick and choose some patterns that would make for a good story – outlining important patterns and presenting them in a visually pleasing way.

The full background and text of the story will be researched by a writer of the magazine – your input should be based on the data and some common sense (i.e. no need to read up on this). It does help, however, to briefly describe what you are presenting and what it highlights.

Provide polished plots that are refined enough to include in the magazine with very little further manipulation (already include variable descriptions [if necessary for understanding], titles, source [e.g. “How Couples Meet and Stay Together (Rosenfeld, Reuben, Falcon 2018)”], appropriate colors, fonts etc.) and are understandable to the average reader of the “New York Times”. The design does not need to be NYTimes-like. Just be consistent.

Data

We will be using the 2017 wave of the HCMST survey - provided as HCMST_couples.rds. The file HCMST_variable_descriptions.pdf contains most of the variable descriptions and coding of responses.

library(plotly)
Registered S3 method overwritten by 'htmlwidgets':
  method           from         
  print.htmlwidget tools:rstudio

Attaching package: ‘plotly’

The following objects are masked from ‘package:plyr’:

    arrange, mutate, rename, summarise

The following object is masked from ‘package:MASS’:

    select

The following object is masked from ‘package:ggplot2’:

    last_plot

The following object is masked from ‘package:stats’:

    filter

The following object is masked from ‘package:graphics’:

    layout

Tasks

2. Age is Just a Number

  1. Create one (1) visualization to show the relationship between a respondent’s age and their partner’s age, accounting for the gender of the respondent? Identify the main pattern in the graph via an annotation directly added to the plot.

Chart 4: Scatterplot

# respondent_age: The age of the respondent = resp_age
# partner_age: The age of their partner = part_age
# gender: The gender of the respondent = resp_gender

# Scatter plot with regression lines
graph_4 <- ggplot(data = df, aes(x = resp_age, y = part_age, color = resp_gender)) +
  geom_point(alpha = 0.5, size=1)+  # Scatter points with some transparency
  geom_smooth(method = "lm", se = TRUE)+ # Adding regression lines
  scale_color_manual(values = c("#567b81", "#af5265", "#7D7C84"))+
  labs(title = "Relationship Between Respondent's Age and Partner's Age",
       x = "Respondent's Age",
       y = "Partner's Age",
       color = "Gender"
       )+
  annotate("text", x = 100, y = 12, label = "Ages couples are positively correlated,
    with slight differences by gender",
    color = "#7D7C84", size = 3.5, fontface= "bold.italic", hjust = 1, linewidth=1)+
  theme_minimal()
Warning: Ignoring unknown parameters: `linewidth`
graph_4

  1. Use Edward Tufte’s principles to critique the plot above. Which of the changes would improve the plot in your opinion?

Answer: If I were Tufte, I would say that the color, the grid lines, and the relatively large data points are unnecessary. Based on data-inc-ration alone, the graph is not at par with what Tuft would have visioned for a effective and compelling vizual aid. I think that the scatter plot would improve (from Tufte standards) from smaller lm lines, and smaller data points. Additionally, I would unbold the annotation/caption.

3. Politics and Dating

  1. Explore how the political affiliation of partners affects how couples meet and stay together. Create two (2) charts in this section. Make sure to use some variation in the type of visualizations. Discuss which visualization you recommend to your editor and why.

Cleaning & Wrangling

# ensure factor levels align 
df$resp_party <- factor(df$resp_party, levels = union(levels(df$resp_party), levels(df$part_party)))
df$part_party <- factor(df$part_party, levels = union(levels(df$resp_party), levels(df$part_party)))

# Creates 2 new categorical variables: summarizes respondents' and partners' political affiliations into three possibilities (dem, ind, rep)
library(dplyr)

df <- df %>%
  mutate(resp_party_type = case_when(
    resp_party %in% c("Strong Democrat", "Not Strong Democrat", "Leans Democrat") ~ "Dem",
    resp_party %in% c("Undecided/Independent/Other") ~ "Ind",
    resp_party %in% c("Strong Republican", "Not Strong Republican", "Leans Republican") ~ "Rep" # Assign NA for any unexpected values
  ))

df <- df %>%
  mutate(part_party_type = case_when(
    part_party %in% c("Strong Democrat", "Not Strong Democrat", "Leans Democrat") ~ "Dem",
    part_party %in% c("Undecided/Independent/Other") ~ "Ind",
    part_party %in% c("Strong Republican", "Not Strong Republican", "Leans Republican") ~ "Rep"
  ))

# Create the alignment variable: party_pair 
df <- df %>%
  mutate(party_pair = paste(resp_party_type, part_party_type, sep = "-"))

# filtering NA pairs
party_pair_filtered <- df %>%
  filter(party_pair != "Dem-NA" & party_pair != "Ind-NA" & party_pair != "Rep-NA")

Graph 5: Stacked Barplot (counts)

#graph 5: Stacked bar chart for meeting types by partner alignment 
graph_5 <- ggplot(party_pair_filtered, aes(x = party_pair, fill = type_met)) +
  geom_bar(position = "Stack") +  # Normalize to proportions
  coord_flip()+
  scale_fill_manual(values = palette)+
  labs(
    title = "Most Popular Meeting Types by Party Alignment",
    x = "Political Alignment",
    y = "Counts",
    fill = "Meeting Type"
  ) +
  theme_minimal()+
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

graph_5

# New DF: Count occurrences of meeting types for each alignment
party_pair_df <- df %>%
  group_by(party_pair, type_met) %>%
  dplyr::summarise(count = n(), .groups = "drop")

Chart 6: Boxplot

# Chart 6: boxplot showing party alignment on duration of relationships  

graph_6 <- ggplot(party_pair_filtered, aes(x = party_pair, y = duration, fill = party_pair)) +
  geom_boxplot() +
  coord_flip()+
  scale_fill_manual(values = c("#567b81", "#567b81", "#567b81", "#d3d3d3", "#d3d3d3", "#d3d3d3", "#af5265", "#af5265", "#af5265"))+
  labs(
    title = "Relationship Duration by Political Alignment",
    x = NULL,
    y = "Duration of Relationship (Years)",
    fill = NULL
  )+ 
  theme_minimal()+ theme(legend.position="none")

graph_6

Discussion:

  1. Write a short narrative (~150 words) based on your visualization, integrating data insights with a compelling story. This narrative should be suitable for a feature article, highlighting key findings and their implications.

Narrative: The way couples meet and the longevity of their relationships seem closely tied to political alignment. Social settings dominate as the most popular meeting type for politically aligned couples, such as “Dem-Dem” and “Rep-Rep,” while mixed-affiliation couples like “Dem-Ind” show a more diverse distribution of meeting types, including online platforms and work-related activities. This suggests that shared political beliefs may streamline social circles, making it easier for like-minded individuals to connect.

When it comes to relationship duration, couples with the same political affiliation, particularly “Dem-Dem” and “Rep-Rep,” tend to have longer-lasting relationships compared to mixed-affiliation pairs. This pattern hints at the stabilizing influence of shared values and worldviews on partnerships. These findings highlight how political identity extends beyond ideology, influencing both how couples form and how they endure over time.

4. Your Turn to Choose

There are lots of other variables that could make for an interesting story, for example, educational background differences, relationship stages (First Met, Romantic, Live together & Married), regional patterns, relationship break ups, sexual behavior etc. Select some variables of your choice to tell a story that captures an interesting insight into the data.

Create one (1) chart in this section to highlight some important patterns. Briefly discuss which visualization you recommend to your editor, why you think the visualization is useful, and which patterns it serves to highlight.

# probability of marriage across meeting types 
df_status_mar <- df %>%
  filter(ship_status== "married")

# Summarize counts of meeting types for married respondents
pie_mar_df <- df_status %>%
  group_by(type_met) %>%
  dplyr::summarise(count = n(), .groups = "drop")

# Pie chart: marriage across meeting types 
graph7.1 <- ggplot(pie_ship_df, aes(x = "", y = count, fill = type_met)) +
  geom_bar(stat = "identity", width = 1, color = "white")+ # Create bars
  scale_fill_manual(values = palette)+
  coord_polar("y", start = 0)+ # Transform to pie chart
  #theme_void() + # Remove axes and grids
  labs(title = "Comparing Meeting Types Between Married and Divorced/Separated Respondents",
    y = "Married", x="percent",
  )+
  theme_minimal()+ 
  theme(legend.position="none")+
  theme(axis.text.x = element_blank(),
    axis.ticks.x = element_blank())
# probability of divorce, separation, breakup across meeting types 
df_status_div_sep <- df %>%
  filter(ended_mar== "divorce" | ended_mar == "separation with no divorce" | ended_nonmar == "We broke up")

# Summarize counts of meeting types for married respondents
pie_nonmar_df <- df_status_div_sep %>%
  group_by(type_met) %>%
  dplyr::summarise(count = n(), .groups = "drop")

# Pie chart: divorce/separation across meeting types 
graph7.2 <-ggplot(pie_nonmar_df, aes(x = "", y = count, fill = type_met)) +
  geom_bar(stat = "identity", width = 1, color = "white")+ 
  scale_fill_manual(values = palette)+
  coord_polar("y", start = 0) + # Transform to pie chart
  #theme_void() + # Remove axes and grids
  labs(
    fill = NULL, x="percent",
    y="Divorced/Separated"
  )+
  theme_minimal()+ 
  theme(
    axis.text.x = element_blank(),   # Remove x-axis text
    axis.ticks.x = element_blank(),  # Remove x-axis ticks
    plot.title = element_text(hjust = 0.5, size = 14), # Center and adjust title size
    legend.position = "none"
  )

graph_7_comb <- graph7.1 + graph7.2
graph_7 <- graph_7_comb + theme(legend.position="right")
graph_7

Discussion: The dual pie chart effectively compares how meeting types differ between married and divorced/separated respondents. It highlights that social settings are prominent for both groups, while work-related activities are more common among married couples. The use of percentages within each slice (observing the two interactive plots) would make the comparison even clearer, allowing readers to easily grasp the relative importance of each meeting type.

Interactivity

5. Make Two Plots Interactive

  1. Choose 2 of the plots you created above and add interactivity. For at least one of these interactive plots, this should not be done through the use of ggplotly

Interactive Plot 1: plotly piechart version

library(plotly)

# Create interactive pie chart
interactive_pie_mar <- plot_ly(
  data = pie_mar_df,
  labels = ~type_met,    # Meeting types as labels
  values = ~count,       # Counts as values
  type = 'pie',          # Specify pie chart
  textinfo = 'label+percent', # Show labels and percentages
  hoverinfo = 'label+value+percent', # Hover info: label, value, percentage
  marker = list(colors = palette) # Custom colors
) %>%
  layout(
    title = "Distribution of Meeting Types Among Married Respondents",
    legend = list(orientation = "h") # Horizontal legend
  )
interactive_pie_mar

# Create interactive pie chart
interactive_pie_divsep <- plot_ly(
  data = pie_nonmar_df,
  labels = ~type_met,    # Meeting types as labels
  values = ~count,       # Counts as values
  type = 'pie',          # Specify pie chart
  textinfo = 'label+percent', # Show labels and percentages
  hoverinfo = 'label+value+percent', # Hover info: label, value, percentage
  marker = list(colors = palette) # Custom colors
) %>%
  layout(
    title = "Distribution of Meeting Types Among Married Respondents",
    legend = list(orientation = "h") # Horizontal legend
  )
interactive_pie_divsep
# Interactive Plot 2:

ggplotly(graph_3)
NA

Interactive Plot 2:

  1. Briefly describe to the editor why interactivity in these visualizations is particularly helpful for a reader, referencing user engagement theories or interaction design principles.

Describe: Interactivity in these visualizations allows readers to explore the data in a more engaging and intuitive way. For example, hovering over the pie chart slices reveals exact percentages and meeting types, making it easier to compare how married and divorced/separated couples met. Similarly, the line graph enables readers to focus on specific trends, such as the sharp rise of online meeting platforms after 2000. These features make the data more accessible and encourage readers to uncover insights on their own.

6. Data Table

To allow the reader to explore the survey data by themselves a bit, select a few useful variables, rename them appropriately for the table to be self-explanatory, and add an interactive data table to the output. Make sure the columns are clearly labeled. Select the appropriate options for the data table (e.g. search bar, sorting, column filters, in-line visualizations etc. – as far as the tools supplied in lecture allow).

# Interactive table:
library(DT)

# Select and rename relevant columns
interactive_tab <- df %>%
  select(
    type_met, 
    ship_status, 
    duration,
    resp_gender,
    resp_party, 
    part_party
  ) %>%
  rename(
    `Meeting Type` = type_met,
    `Relationship Status` = ship_status,
    `Length of Relationship (Years)` = duration,
    `Respondent's Gender` = resp_gender,
    `Respondent's Political Affiliation` = resp_party,
    `Partner's Political Affiliation` = part_party
  )

# Create the interactive data table
datatable(
  interactive_tab,
  class = "cell-border stripe hover compact",  # Styling options
  filter = "top",                              # Add column filters at the top
  options = list(
    pageLength = 10,                           # Number of rows per page
    autoWidth = TRUE,                          # Automatically adjust column widths
    dom = 'Bfrtip',                            # Add buttons for export/download
    buttons = c('copy', 'csv', 'excel')        # Export options
  ),
  caption = "Explore Meeting Types and Relationship Details of Survey Respondents"
)

Technical Details

The data comes in a reasonably clean file. However, if you do find issues with the data, recode any values, etc. please make this clear in the code (and if significant add into the description).

If needed for your visualization, you can add visual drapery like icons, images etc. but you are certainly not obligated to do that. What is important, however, to use a consistent style across all your visualizations.

Part of the task will be transforming the dataset into a shape that allows you to plot what you want. For some plots, you will necessarily need to be selective in what to include and what to leave out.

Make sure to use at least three different types of graphs, e.g. line graphs, scatter, histograms, bar charts, dot plots, heat maps, etc.

Submission

Please follow the instructions to submit your homework. The homework is due on Friday, February 21 at 5pm.

Please Stay Honest!

Yes, this type of data has been analyzed before. If you do come across something, please no wholesale copying of other ideas. We are trying to evaluate your abilities in using the packages we discussed to create data visualization not the ability to do internet searches. Similarly, please stay away from solutions / code created by generative AI. Here is your chance to learn and apply the concepts we have discussed in class!

Also, this is an individually assigned exercise – please keep your solution to yourself!

LS0tCnRpdGxlOiAiQXNzaWdubWVudCAxIC0gRGF0aW5nIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKZGF0ZTogMjAyNS0wMi0xMgphdXRob3I6IFRob21hcyBCcmFtYm9yCi0tLQoKIVtdKGltYWdlcy9jbGlwYm9hcmQtMjM0ODQ3NDExOC5wbmcpCgojIyBTY2VuYXJpbwoKSW1hZ2luZSB5b3UgYXJlIGEgZGF0YSBzY2llbnRpc3QgYXQgYSByZXNwZWN0ZWQgbWVkaWEgb3V0bGV0IC0tIHNheSB0aGUgIk5ldyBZb3JrIFRpbWVzIi4gWW91ciBlZGl0b3Igd2FudHMgdG8gc3VwcG9ydCB0aGUgd3JpdGluZyBvZiBhIGZlYXR1cmUgYXJ0aWNsZSBhYm91dCAqSG93IENvdXBsZXMgTWVldCBhbmQgU3RheSBUb2dldGhlciouIFlvdXIgZWRpdG9yLWluLWNoaWVmIGFza3MgeW91IHRvIGFuYWx5emUgc29tZSBkYXRhIGZyb20gYW4gW2V4dGVuc2l2ZSBzdXJ2ZXkgY29uZHVjdGVkIGJ5IGEgcmVzZWFyY2hlciBhdCBTdGFuZm9yZCBVbml2ZXJzaXR5XShodHRwczovL2RhdGEuc3RhbmZvcmQuZWR1L2hjbXN0KS4KClNpbmNlIHRoZXJlIGlzICoqbm8gd2F5IHRoYXQgYWxsIGZlYXR1cmVzIG9mIHRoZSBkYXRhIGNhbiBiZSByZXByZXNlbnRlZCoqIGluIHN1Y2ggYSBtZW1vLCBmZWVsIGZyZWUgdG8gcGljayBhbmQgY2hvb3NlIHNvbWUgcGF0dGVybnMgdGhhdCB3b3VsZCBtYWtlIGZvciBhIGdvb2Qgc3RvcnkgLS0gb3V0bGluaW5nIGltcG9ydGFudCBwYXR0ZXJucyBhbmQgcHJlc2VudGluZyB0aGVtIGluIGEgdmlzdWFsbHkgcGxlYXNpbmcgd2F5LgoKVGhlIGZ1bGwgYmFja2dyb3VuZCBhbmQgdGV4dCBvZiB0aGUgc3Rvcnkgd2lsbCBiZSByZXNlYXJjaGVkIGJ5IGEgd3JpdGVyIG9mIHRoZSBtYWdhemluZSAtLSB5b3VyIGlucHV0IHNob3VsZCBiZSBiYXNlZCBvbiB0aGUgZGF0YSBhbmQgc29tZSBjb21tb24gc2Vuc2UgKGkuZS4gbm8gbmVlZCB0byByZWFkIHVwIG9uIHRoaXMpLiBJdCBkb2VzIGhlbHAsIGhvd2V2ZXIsIHRvIGJyaWVmbHkgZGVzY3JpYmUgd2hhdCB5b3UgYXJlIHByZXNlbnRpbmcgYW5kIHdoYXQgaXQgaGlnaGxpZ2h0cy4KClByb3ZpZGUgKipwb2xpc2hlZCBwbG90cyoqIHRoYXQgYXJlIHJlZmluZWQgZW5vdWdoIHRvIGluY2x1ZGUgaW4gdGhlIG1hZ2F6aW5lIHdpdGggdmVyeSBsaXR0bGUgZnVydGhlciBtYW5pcHVsYXRpb24gKGFscmVhZHkgaW5jbHVkZSB2YXJpYWJsZSBkZXNjcmlwdGlvbnMgW2lmIG5lY2Vzc2FyeSBmb3IgdW5kZXJzdGFuZGluZ10sIHRpdGxlcywgc291cmNlIFtlLmcuICJIb3cgQ291cGxlcyBNZWV0IGFuZCBTdGF5IFRvZ2V0aGVyIChSb3NlbmZlbGQsIFJldWJlbiwgRmFsY29uIDIwMTgpIl0sIGFwcHJvcHJpYXRlIGNvbG9ycywgZm9udHMgZXRjLikgYW5kIGFyZSB1bmRlcnN0YW5kYWJsZSB0byB0aGUgYXZlcmFnZSByZWFkZXIgb2YgdGhlICJOZXcgWW9yayBUaW1lcyIuIFRoZSBkZXNpZ24gZG9lcyBub3QgbmVlZCB0byBiZSBOWVRpbWVzLWxpa2UuIEp1c3QgYmUgY29uc2lzdGVudC4KCiMjIERhdGEKCldlIHdpbGwgYmUgdXNpbmcgdGhlIDIwMTcgd2F2ZSBvZiB0aGUgSENNU1Qgc3VydmV5IC0gcHJvdmlkZWQgYXMgYEhDTVNUX2NvdXBsZXMucmRzYC4gVGhlIGZpbGUgYEhDTVNUX3ZhcmlhYmxlX2Rlc2NyaXB0aW9ucy5wZGZgIGNvbnRhaW5zIG1vc3Qgb2YgdGhlIHZhcmlhYmxlIGRlc2NyaXB0aW9ucyBhbmQgY29kaW5nIG9mIHJlc3BvbnNlcy4KCmBgYHtyfQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShnZ3RoZW1lcykKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KGZvcmNhdHMpCmxpYnJhcnkocGxvdGx5KQpsaWJyYXJ5KERUKQoKCnNldHdkKCJ+L0Rlc2t0b3AvU3ByaW5nIDIwMjUvRGF0YSBWaXovUiBEaXJlY3RvcnkgLSBEYXRhX1Zpei8wM19kYXRpbmdfR1JBREVEIikKZmlsZW5hbWUgPC0gZmlsZS5jaG9vc2UoKQpjb3VwbGVzIDwtIHJlYWRSRFMoZmlsZW5hbWUpCgojIGV4dHJhY3RpbmcgdmFycyBhbmQgY3JlYXRpbmcgZGYKZGYgPC0gZGF0YS5mcmFtZShJRCA9IGNvdXBsZXMkQ2FzZUlELCAKICAgICAgICAgICAgICAgICBjb3VwbGVzJERPVl9CcmFuY2gsIAogICAgICAgICAgICAgICAgIHNoaXBfc3RhdHVzID0gY291cGxlcyRwYXJ0bmVyc2hpcF9zdGF0dXMsIAogICAgICAgICAgICAgICAgIG1lZXRpbmdfdHlwZSA9IGNvdXBsZXMkbWVldGluZ190eXBlLCAKICAgICAgICAgICAgICAgICB5ZWFyX21ldCA9IGNvdXBsZXMkUTIxQV9ZZWFyLCAKICAgICAgICAgICAgICAgICBtb250aF9tZXQgPSBjb3VwbGVzJFEyMUFfTW9udGgsCiAgICAgICAgICAgICAgICAgeWVhcl9iZWdpbiA9IGNvdXBsZXMkUTIxQl9ZZWFyLAogICAgICAgICAgICAgICAgIHllYXJfbGl2X3RvZyA9IGNvdXBsZXMkUTIxQ19ZZWFyLAogICAgICAgICAgICAgICAgIHllYXJfbWFyID0gY291cGxlcyRRMjFEX1llYXIsCiAgICAgICAgICAgICAgICAgcmVzcF9hZ2UgPSBjb3VwbGVzJHBwYWdlLAogICAgICAgICAgICAgICAgIHBhcnRfYWdlID0gY291cGxlcyRROSwKICAgICAgICAgICAgICAgICByZXNwX2dlbmRlciA9IGNvdXBsZXMkcHBnZW5kZXIsCiAgICAgICAgICAgICAgICAgZHVyYXRpb24gPSBjb3VwbGVzJHJlbGF0ZV9kdXJhdGlvbl9hdF93Nl95ZWFycywKICAgICAgICAgICAgICAgICBzaGlwX3N0YXR1cyA9IGNvdXBsZXMkcGFydG5lcnNoaXBfc3RhdHVzLCAKICAgICAgICAgICAgICAgICByZXNwX3BhcnR5ID0gY291cGxlcyRwYXJ0eWlkNywKICAgICAgICAgICAgICAgICBwYXJ0X3BhcnR5ID0gY291cGxlcyR3Nl9xMTIsCiAgICAgICAgICAgICAgICAgZW5kZWRfbm9ubWFyID0gY291cGxlcyR3Nl9yZWxhdGlvbnNoaXBfZW5kX25vbm1hciwgCiAgICAgICAgICAgICAgICAgZW5kZWRfbWFyID0gY291cGxlcyR3Nl9yZWxhdGlvbnNoaXBfZW5kX21hcgogICAgICAgICAgICAgICAgICkKYGBgCgojIyBUYXNrcwoKIyMjIDEuIERhdGluZyBUcmVuZHMgT3ZlciBUaW1lCgphKSAgVmlzdWFsaXplIGhvdyB0aGUgbW9kZSBvZiBtZWV0aW5nIGZvciB0aGUgZmlyc3QgdGltZSBoYXMgY2hhbmdlZCBvdmVyIHRoZSB5ZWFycy4gQ3JlYXRlIHR3byAoMikgY2hhcnRzIGluIHRoaXMgc2VjdGlvbiB0byBoaWdobGlnaHQgc29tZSBpbXBvcnRhbnQgcGF0dGVybihzKS4KCioqV3JhbmdsaW5nIGFuZCBDbGVhbmluZyoqCgpgYGB7cn0KIyBncm91cGluZyBtZWV0aW5nIHBsYWNlcyBpbnRvIDYgY2F0ZWdvcmllcyBbdHlwZV9tZXRdCmRmIDwtIGRmICU+JQogIG11dGF0ZSh0eXBlX21ldCA9IGNhc2Vfd2hlbigKICAgIG1lZXRpbmdfdHlwZSAlaW4lIGMoIkludGVybmV0IiwgIkludGVybmV0IERhdGluZyBvciBQaG9uZSBBcHAiLCAiSW50ZXJuZXQgU29jaWFsIE5ldHdvcmsiLCAiT25saW5lIEdhbWluZyIsICJJbnRlcm5ldCBDaGF0IiwgIkludGVybmV0IFNpdGUiLCAiTWV0IE9ubGluZSIpIH4gIk9ubGluZSIsCiAgICBtZWV0aW5nX3R5cGUgJWluJSBjKCJQcmltYXJ5IG9yIFNlY29uZGFyeSBTY2hvb2wiLCAiQ29sbGVnZSIpIH4gIlNjaG9vbC9Db2xsZWdlIiwKICAgIG1lZXRpbmdfdHlwZSAlaW4lIGMoIkJ1c2luZXNzIFRyaXAiLCAiV29yayBOZWlnaGJvcnMiLCAiQ3VzdG9tZXItQ2xpZW50IFJlbGF0aW9uc2hpcCIpIH4gIldvcmstUmVsYXRlZCBBY3Rpdml0eSIsCiAgICBtZWV0aW5nX3R5cGUgJWluJSBjKCJCYXIgb3IgUmVzdGF1cmFudCIsICJQcml2YXRlIFBhcnR5IiwgIkNodXJjaCIsICJWb2x1bnRlZXIgT3JnYW5pemF0aW9uIikgfiAiU29jaWFsIFNldHRpbmdzIiwKICAgIG1lZXRpbmdfdHlwZSAlaW4lIGMoIkJsaW5kIERhdGUiLCAiTWlsaXRhcnkiLCAiT25lLXRpbWUgU2VydmljZSBJbnRlcmFjdGlvbiIsICJPbiBWYWNhdGlvbiIsICJQdWJsaWMgUGxhY2UiKSB+ICJTcGVjaWFsIENpcmN1bXN0YW5jZS9PdGhlciIsCiAgICBUUlVFIH4gIk90aGVyIgogICkpCgojIGZpbHRlciB0byBvbmx5IHJvd3Mgd2l0aCB5ZWFycyByZXBvcnRlZCAobm8gTkEncyBvciAnUmVmdXNlZCcpIApkZl9maWx0ZXJlZCA8LSBmaWx0ZXIoZGYsICFpcy5uYSh5ZWFyX21ldCkgJiB5ZWFyX21ldCAhPSAiUmVmdXNlZCIpCgojIFByZXBhcmluZyBmb3IgY2hhcnQgMiBkYXRhIApkZl9maWx0ZXJlZCR5ZWFyc19tZXRfbnVtIDwtIGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKGRmX2ZpbHRlcmVkJHllYXJfbWV0KSkKCiMgR3JvdXAgeWVhcnMgaW50byAxMC15ZWFyIGludGVydmFscyBzdGFydGluZyBmcm9tIDE5MzAKZGZfZmlsdGVyZWQgPC0gZGZfZmlsdGVyZWQgJT4lCiAgbXV0YXRlKHllYXJfZ3JvdXAgPSBjdXQoeWVhcnNfbWV0X251bSwKICAgICAgICAgICAgICAgICAgICAgICAgICBicmVha3MgPSBzZXEoMTkzMCwgMjA0MCwgYnkgPSAxMCksICMgRGVmaW5lIGRlY2FkZSBpbnRlcnZhbHMKICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCIxOTMwLTE5MzkiLCAiMTk0MC0xOTQ5IiwgIjE5NTAtMTk1OSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjE5NjAtMTk2OSIsICIxOTcwLTE5NzkiLCAiMTk4MC0xOTg5IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiMTk5MC0xOTk5IiwgIjIwMDAtMjAwOSIsICIyMDEwLTIwMTkiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjIwMjAtMjAyOSIsICIyMDMwLTIwMzkiKSwKICAgICAgICAgICAgICAgICAgICAgICAgICByaWdodCA9IEZBTFNFKSkgIyBMZWZ0LWluY2x1c2l2ZSBpbnRlcnZhbHMKCmBgYAoKKipDdXN0b20gUGFsZXR0ZSoqCgpgYGB7cn0KcGFsZXR0ZSA8LSBjKCIjN0Q3Qzg0IiwgIiNhZjUyNjUiLCAiI2Y5Yjk3ZiIsICIjZDNkM2QzIiwgIiM1NjdiODEiKQpgYGAKCioqQmFzZSBncmFwaCoqCgpgYGB7cn0KIyBCYXNlIGdyYXBoOiBNb2RlIG9mIG1lZXRpbmcgW0FsbCByZXNwb25kZW50c11bbm8gdGltZV1bb3ZlcmFsbF0KYmFzZV9ncmFwaCA8LSBnZ3Bsb3QoZGYsIGFlcyh4ID0gZmN0X3JldihmY3RfaW5mcmVxKHR5cGVfbWV0KSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsbD0gdHlwZV9tZXQsICMgZGlmZmVyZW50IGNvbG9yIGJ5IG1lZXRpbmcgdHlwZSAKICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0ID0gImlkZW50aXR5IikpKyAKICBnZW9tX2Jhcih3aWR0aCA9IDAuNikrCiAgY29vcmRfZmxpcCgpKyAjdHVybnMgdGhlIGJveHBsb3Qgb24gaXRzIHNpZGUKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBwYWxldHRlKSsgI3BhbGV0dGUKICBsYWJzKHg9TlVMTCwgeT0gIkNvdW50cyIsIHRpdGxlID0gIkhvdyBkaWQgeW91IG1lZXQgeW91ciBwYXJ0bmVyPyIsIGZpbGwgPSAiTWVldGluZyBUeXBlIikrCiAgdGhlbWVfbWluaW1hbCgpCgpiYXNlX2dyYXBoICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQoKYGBgCgoqKkNoYXJ0IDE6IHN0YWNrZWQgYmFyIChjb3VudHMpKioKCmBgYHtyfQojIENoYXJ0IDE6IE1lZXRpbmcgbW9kZSwgZnJlcXVlbmN5IG92ZXIgdGltZSBbZmlsdGVycyBOQXMgJiAnUmVmdXNlZCddCgojIEVuc3VyZSB5ZWFyX21ldCBpcyBudW1lcmljCmRmX2ZpbHRlcmVkIDwtIGRmX2ZpbHRlcmVkICU+JQogIG11dGF0ZSh5ZWFyX21ldCA9IGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKHllYXJfbWV0KSkpICAjIENvbnZlcnQgZmFjdG9yIHRvIG51bWVyaWMKCiMgU3RhY2tlZCBiYXIgcGxvdCwgb3ZlciB0aW1lIFt5ZWFyX21ldDogdW5ncm91cGVkXQpncmFwaF8xIDwtIGdncGxvdChkZl9maWx0ZXJlZCwgYWVzKHggPSB5ZWFyX21ldCwgZmlsbCA9IHR5cGVfbWV0KSkrCiAgZ2VvbV9iYXIod2lkdGggPSAuNzUpKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMTk0MCwgMjAyMCwgYnkgPSAxMCkpKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IHBhbGV0dGUpKwogIGxhYnMoeCA9IE5VTEwsIHkgPSAiQ291bnRzIiwgZmlsbCA9ICJNZWV0aW5nIFR5cGUiLAogICAgICAgdGl0bGUgPSAiSG93IHBlb3BsZSBtZXQgdGhlaXIgcGFydG5lcnMgb3ZlciB0aW1lIChmcmVxdWVuY3kpIikrCiAgY29vcmRfZml4ZWQocmF0aW8gPSAwLjIpICsgICMgQWRqdXN0IGFzcGVjdCByYXRpbyAoc21hbGxlciB2YWx1ZXMgc3RyZXRjaCBob3Jpem9udGFsbHkpKwogIHRoZW1lX21pbmltYWwoKSsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDc1LCBoanVzdCA9IDAuOCwgc2l6ZSA9IDcpKQogIApncmFwaF8xCgpgYGAKCioqR3JhcGggMjogc3RhY2tlZCBiYXIgKHByb3BvcnRpb25zKShncm91cGVkKSoqCgpgYGB7cn0KIyBHcmFwaCAyOiBNZWV0aW5nIG1vZGUsIHBlcmNlbnRhZ2Ugb3ZlciB0aW1lIFtmaWx0ZXJzIE5Bc11bU3RhY2tlZCBCYXIgQ2hhcnRdCgojIEZpbGxlZCBiYXIgcGxvdCwgb3ZlciB0aW1lIApncmFwaF8yIDwtIGdncGxvdChkZl9maWx0ZXJlZCwgYWVzKHg9eWVhcl9ncm91cCwgZmlsbD10eXBlX21ldCkpKwogIGdlb21fYmFyKHBvc2l0aW9uID0gImZpbGwiLCB3aWR0aCA9IDAuNikrCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gcGFsZXR0ZSkrCiAgbGFicyh4ID0gIkRlY2FkZSIsIHkgPSAiUGVyY2VudCglKSIsIGZpbGwgPSAiTWVldGluZyBUeXBlIiwKICAgICAgIHRpdGxlID0gIkhvdyBwZW9wbGUgbWV0IHRoZWlyIHBhcnRuZXJzIG92ZXIgdGltZSAoJSkiKSsKICB0aGVtZV9taW5pbWFsKCkrCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA3MCwgaGp1c3QgPSAxLCB2anVzdCA9IDEuMTUsIHNpemU9NykpCgpncmFwaF8yCmBgYAoKYikgIENyZWF0ZSBhbiBhbHRlcm5hdGl2ZSB2aXN1YWxpemF0aW9uIG9mIHRoZSBzYW1lIGRhdGEuIERpc2N1c3Mgd2hpY2ggdmlzdWFsaXphdGlvbiB5b3UgcmVjb21tZW5kIHRvIHRoZSBlZGl0b3IgYW5kIHdoeS4gUmVseSBvbiBhdCBsZWFzdCB0aHJlZSBzcGVjaWZpYyBkYXRhIHZpc3VhbGl6YXRpb24gcHJpbmNpcGxlcyBvciB0aGVvcmllcyBkaXNjdXNzZWQgaW4gY2xhc3MgdG8ganVzdGlmeSB5b3VyIGNob2ljZS4KCioqQ2hhcnQgMzogTGluZSBHcmFwaCAoQWx0ZXJuYXRpdmUpKioKCmBgYHtyfQojZnJlcXVlbmN5IChjb3VudHMpIG9mIG1lZXRpbmcgdHlwZSBvdmVyIHRpbWUKCiMgZGF0YWZyYW1lOiBjb3VudCBtZWV0aW5nIHR5cGVzIGJ5IHllYXIKbGluZSA8LSBkZl9maWx0ZXJlZCAlPiUKICBncm91cF9ieSh5ZWFyX21ldCwgdHlwZV9tZXQpICU+JSAgIyBHcm91cCBieSB5ZWFyIGFuZCBtZWV0aW5nIHR5cGUKICBkcGx5cjo6c3VtbWFyaXNlKGNvdW50ID0gbigpLCAuZ3JvdXBzID0gImRyb3AiKSAgIyBDb3VudCBvY2N1cnJlbmNlcywgdXNpbmcgZHBseXIgcGFja2FnZSAKCiMgQmFzaWMgbGluZSBncmFwaApncmFwaF8zIDwtIGdncGxvdChsaW5lLCBhZXMoeCA9IHllYXJfbWV0LCB5ID0gY291bnQsIGNvbG9yID0gdHlwZV9tZXQsIGdyb3VwID0gdHlwZV9tZXQpKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IHBhbGV0dGUpKwogIGdlb21fbGluZShhbHBoYT0wLjg1LCBsaW5ld2lkdGggPSAwLjc1KSsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDE5NDAsIDIwMjAsIGJ5ID0gMTApKSsKICBnZW9tX3BvaW50KGFscGhhPTAuNzUsIHNpemU9MSkrCiAgY29vcmRfZml4ZWQocmF0aW8gPSAwLjUpICsgCiAgbGFicygKICAgIHRpdGxlID0gIk1lZXRpbmcgVHlwZSBQb3B1bGF0aXR5IE92ZXIgVGltZSIsCiAgICB4ID0gIlllYXIiLAogICAgeSA9ICJDb3VudCIsCiAgICBjb2xvciA9ICJNZWV0aW5nIFR5cGUiCiAgKSsgCiAgdGhlbWVfbWluaW1hbCgpKyAKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDc1LCBoanVzdCA9IDEsIHNpemUgPSA3KSkgIyBBZGQgbGluZXMgZm9yIGVhY2ggbWVldGluZyB0eXBlCgpncmFwaF8zCmBgYAoKKipNeSByZWNvbW1lbmRhdGlvbioqOiBDaGFydCAxIGlzIG5pY2UgZm9yIHZpc3VhbGl6aW5nIGNoYW5nZXMgaW4gdGhlIHRoZSBmcmVxdWVuY3kgb2YgbW9kZXMgZXZlcnkgeWVhciwgd2hpbGUgZHJhd2luZyBhdHRlbnRpb24gdG8gdGhlIHJpc2Ugb2Ygc29tZSBtb2RlcyAoaS5lLiwgaW50ZXJuZXQpLiBIb3dldmVyLCBjaGFydCAxIG1pZ2h0IG5vdCBiZSB0aGUgYmVzdCBtZWFucyBvZiBjb21wYXJpbmcgcHJvcG9ydGlvbmFsIGRpc3RyaWJ1dGlvbi4gVG8gY29tYmF0IHRoaXMsIGNoYXJ0IDIgd2FzIGNyZWF0ZWQgdG8gZXhwbG9yZSB0aGUgc2hhcmUgKCUpLCB3aXRoIHllYXJzIGdyb3VwZWQgaW50byBkZWNhZGVzLiBXaGlsZSBjaGFydCAyIGRvZXMgYSBiZXR0ZXIgam9iIHRoYW4gY2hhcnQgMSBhdCBoaWdobGlnaHRpbmcgd2hpY2ggbW9kZXMgYXJlIG1vcmUgcG9wdWxhciB0aGFuIG90aGVycyBvdmVyIHRpbWUsIGFnZ3JlZ2F0aW5nIGJ5IGRlY2FkZSByZXN1bHRzIGluIG1lYXN1cmVtZW50IGVycm9yIHdoaWNoIGNhbiBtaXNsZWFkIHZpZXdlcnMgLS0gYSBsb3Qgb2YgY2hhbmdlcyBjYW4gaGFwcGVuIGluIDEwIHllYXJzLiBUaGUgbGFzdCB2aXp1YWxpemF0aW9uLCBjaGFydCAzLCBjaXJjdW12ZW50cyB0aGVzZSBpc3N1ZXMuIE5vdCBvbmx5IGRvZXMgYSBmcmVxdWVuY3ktYmFzZWQgbGluZSBncmFwaCBhbGxvdyB2aWV3ZXJzIHRvIGNsZWFybHkgZGVjaXBoZXIgd2hpY2ggbW9kZXMgYXJlIGFib3ZlIGFuZCBiZWxvdyBvdGhlcnMgaW4gdGVybXMgb2YgcG9wdWxhcml0eSwgYnV0IGl0IGFsc28gYWxsb3dzIHVzIHRvIGNvbXBhcmUgYWNyb3NzIGFsbCB5ZWFycy4gSSB3b3VsZCByZWNvbW1lbmQgY2hhcnQgMy4KCiMjIyAyLiBBZ2UgaXMgSnVzdCBhIE51bWJlcgoKYSkgIENyZWF0ZSBvbmUgKDEpIHZpc3VhbGl6YXRpb24gdG8gc2hvdyB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gYSByZXNwb25kZW50J3MgYWdlIGFuZCB0aGVpciBwYXJ0bmVyJ3MgYWdlLCBhY2NvdW50aW5nIGZvciB0aGUgZ2VuZGVyIG9mIHRoZSByZXNwb25kZW50PyBJZGVudGlmeSB0aGUgbWFpbiBwYXR0ZXJuIGluIHRoZSBncmFwaCB2aWEgYW4gYW5ub3RhdGlvbiBkaXJlY3RseSBhZGRlZCB0byB0aGUgcGxvdC4KCioqQ2hhcnQgNDogU2NhdHRlcnBsb3QqKgoKYGBge3J9CiMgcmVzcG9uZGVudF9hZ2U6IFRoZSBhZ2Ugb2YgdGhlIHJlc3BvbmRlbnQgPSByZXNwX2FnZQojIHBhcnRuZXJfYWdlOiBUaGUgYWdlIG9mIHRoZWlyIHBhcnRuZXIgPSBwYXJ0X2FnZQojIGdlbmRlcjogVGhlIGdlbmRlciBvZiB0aGUgcmVzcG9uZGVudCA9IHJlc3BfZ2VuZGVyCgojIFNjYXR0ZXIgcGxvdCB3aXRoIHJlZ3Jlc3Npb24gbGluZXMKZ3JhcGhfNCA8LSBnZ3Bsb3QoZGF0YSA9IGRmLCBhZXMoeCA9IHJlc3BfYWdlLCB5ID0gcGFydF9hZ2UsIGNvbG9yID0gcmVzcF9nZW5kZXIpKSArCiAgZ2VvbV9wb2ludChhbHBoYSA9IDAuNSwgc2l6ZT0xKSsgICMgU2NhdHRlciBwb2ludHMgd2l0aCBzb21lIHRyYW5zcGFyZW5jeQogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gVFJVRSkrICMgQWRkaW5nIHJlZ3Jlc3Npb24gbGluZXMKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiIzU2N2I4MSIsICIjYWY1MjY1IiwgIiM3RDdDODQiKSkrCiAgbGFicyh0aXRsZSA9ICJSZWxhdGlvbnNoaXAgQmV0d2VlbiBSZXNwb25kZW50J3MgQWdlIGFuZCBQYXJ0bmVyJ3MgQWdlIiwKICAgICAgIHggPSAiUmVzcG9uZGVudCdzIEFnZSIsCiAgICAgICB5ID0gIlBhcnRuZXIncyBBZ2UiLAogICAgICAgY29sb3IgPSAiR2VuZGVyIgogICAgICAgKSsKICBhbm5vdGF0ZSgidGV4dCIsIHggPSAxMDAsIHkgPSAxMiwgbGFiZWwgPSAiQWdlcyBjb3VwbGVzIGFyZSBwb3NpdGl2ZWx5IGNvcnJlbGF0ZWQsCiAgICB3aXRoIHNsaWdodCBkaWZmZXJlbmNlcyBieSBnZW5kZXIiLAogICAgY29sb3IgPSAiIzdEN0M4NCIsIHNpemUgPSAzLjUsIGZvbnRmYWNlPSAiYm9sZC5pdGFsaWMiLCBoanVzdCA9IDEsIGxpbmV3aWR0aD0xKSsKICB0aGVtZV9taW5pbWFsKCkKCmdyYXBoXzQKYGBgCgpiKSAgVXNlIEVkd2FyZCBUdWZ0ZSdzIHByaW5jaXBsZXMgdG8gY3JpdGlxdWUgdGhlIHBsb3QgYWJvdmUuIFdoaWNoIG9mIHRoZSBjaGFuZ2VzIHdvdWxkIGltcHJvdmUgdGhlIHBsb3QgaW4geW91ciBvcGluaW9uPwoKKipBbnN3ZXIqKjogSWYgSSB3ZXJlIFR1ZnRlLCBJIHdvdWxkIHNheSB0aGF0IHRoZSBjb2xvciwgdGhlIGdyaWQgbGluZXMsIGFuZCB0aGUgcmVsYXRpdmVseSBsYXJnZSBkYXRhIHBvaW50cyBhcmUgdW5uZWNlc3NhcnkuIEJhc2VkIG9uIGRhdGEtaW5jLXJhdGlvbiBhbG9uZSwgdGhlIGdyYXBoIGlzIG5vdCBhdCBwYXIgd2l0aCB3aGF0IFR1ZnQgd291bGQgaGF2ZSB2aXNpb25lZCBmb3IgYSBlZmZlY3RpdmUgYW5kIGNvbXBlbGxpbmcgdml6dWFsIGFpZC4gSSB0aGluayB0aGF0IHRoZSBzY2F0dGVyIHBsb3Qgd291bGQgaW1wcm92ZSAoZnJvbSBUdWZ0ZSBzdGFuZGFyZHMpIGZyb20gc21hbGxlciBsbSBsaW5lcywgYW5kIHNtYWxsZXIgZGF0YSBwb2ludHMuIEFkZGl0aW9uYWxseSwgSSB3b3VsZCB1bmJvbGQgdGhlIGFubm90YXRpb24vY2FwdGlvbi4KCiMjIyAzLiBQb2xpdGljcyBhbmQgRGF0aW5nCgphKSAgRXhwbG9yZSBob3cgdGhlIHBvbGl0aWNhbCBhZmZpbGlhdGlvbiBvZiBwYXJ0bmVycyBhZmZlY3RzIGhvdyBjb3VwbGVzIG1lZXQgYW5kIHN0YXkgdG9nZXRoZXIuIENyZWF0ZSB0d28gKDIpIGNoYXJ0cyBpbiB0aGlzIHNlY3Rpb24uIE1ha2Ugc3VyZSB0byB1c2Ugc29tZSB2YXJpYXRpb24gaW4gdGhlIHR5cGUgb2YgdmlzdWFsaXphdGlvbnMuIERpc2N1c3Mgd2hpY2ggdmlzdWFsaXphdGlvbiB5b3UgcmVjb21tZW5kIHRvIHlvdXIgZWRpdG9yIGFuZCB3aHkuCgoqKkNsZWFuaW5nICYgV3JhbmdsaW5nKioKCmBgYHtyfQojIGVuc3VyZSBmYWN0b3IgbGV2ZWxzIGFsaWduIApkZiRyZXNwX3BhcnR5IDwtIGZhY3RvcihkZiRyZXNwX3BhcnR5LCBsZXZlbHMgPSB1bmlvbihsZXZlbHMoZGYkcmVzcF9wYXJ0eSksIGxldmVscyhkZiRwYXJ0X3BhcnR5KSkpCmRmJHBhcnRfcGFydHkgPC0gZmFjdG9yKGRmJHBhcnRfcGFydHksIGxldmVscyA9IHVuaW9uKGxldmVscyhkZiRyZXNwX3BhcnR5KSwgbGV2ZWxzKGRmJHBhcnRfcGFydHkpKSkKCiMgQ3JlYXRlcyAyIG5ldyBjYXRlZ29yaWNhbCB2YXJpYWJsZXM6IHN1bW1hcml6ZXMgcmVzcG9uZGVudHMnIGFuZCBwYXJ0bmVycycgcG9saXRpY2FsIGFmZmlsaWF0aW9ucyBpbnRvIHRocmVlIHBvc3NpYmlsaXRpZXMgKGRlbSwgaW5kLCByZXApCmxpYnJhcnkoZHBseXIpCgpkZiA8LSBkZiAlPiUKICBtdXRhdGUocmVzcF9wYXJ0eV90eXBlID0gY2FzZV93aGVuKAogICAgcmVzcF9wYXJ0eSAlaW4lIGMoIlN0cm9uZyBEZW1vY3JhdCIsICJOb3QgU3Ryb25nIERlbW9jcmF0IiwgIkxlYW5zIERlbW9jcmF0IikgfiAiRGVtIiwKICAgIHJlc3BfcGFydHkgJWluJSBjKCJVbmRlY2lkZWQvSW5kZXBlbmRlbnQvT3RoZXIiKSB+ICJJbmQiLAogICAgcmVzcF9wYXJ0eSAlaW4lIGMoIlN0cm9uZyBSZXB1YmxpY2FuIiwgIk5vdCBTdHJvbmcgUmVwdWJsaWNhbiIsICJMZWFucyBSZXB1YmxpY2FuIikgfiAiUmVwIiAjIEFzc2lnbiBOQSBmb3IgYW55IHVuZXhwZWN0ZWQgdmFsdWVzCiAgKSkKCmRmIDwtIGRmICU+JQogIG11dGF0ZShwYXJ0X3BhcnR5X3R5cGUgPSBjYXNlX3doZW4oCiAgICBwYXJ0X3BhcnR5ICVpbiUgYygiU3Ryb25nIERlbW9jcmF0IiwgIk5vdCBTdHJvbmcgRGVtb2NyYXQiLCAiTGVhbnMgRGVtb2NyYXQiKSB+ICJEZW0iLAogICAgcGFydF9wYXJ0eSAlaW4lIGMoIlVuZGVjaWRlZC9JbmRlcGVuZGVudC9PdGhlciIpIH4gIkluZCIsCiAgICBwYXJ0X3BhcnR5ICVpbiUgYygiU3Ryb25nIFJlcHVibGljYW4iLCAiTm90IFN0cm9uZyBSZXB1YmxpY2FuIiwgIkxlYW5zIFJlcHVibGljYW4iKSB+ICJSZXAiCiAgKSkKCiMgQ3JlYXRlIHRoZSBhbGlnbm1lbnQgdmFyaWFibGU6IHBhcnR5X3BhaXIgCmRmIDwtIGRmICU+JQogIG11dGF0ZShwYXJ0eV9wYWlyID0gcGFzdGUocmVzcF9wYXJ0eV90eXBlLCBwYXJ0X3BhcnR5X3R5cGUsIHNlcCA9ICItIikpCgojIGZpbHRlcmluZyBOQSBwYWlycwpwYXJ0eV9wYWlyX2ZpbHRlcmVkIDwtIGRmICU+JQogIGZpbHRlcihwYXJ0eV9wYWlyICE9ICJEZW0tTkEiICYgcGFydHlfcGFpciAhPSAiSW5kLU5BIiAmIHBhcnR5X3BhaXIgIT0gIlJlcC1OQSIpCgpgYGAKCioqR3JhcGggNTogU3RhY2tlZCBCYXJwbG90IChjb3VudHMpKioKCmBgYHtyfQojZ3JhcGggNTogU3RhY2tlZCBiYXIgY2hhcnQgZm9yIG1lZXRpbmcgdHlwZXMgYnkgcGFydG5lciBhbGlnbm1lbnQgCmdyYXBoXzUgPC0gZ2dwbG90KHBhcnR5X3BhaXJfZmlsdGVyZWQsIGFlcyh4ID0gcGFydHlfcGFpciwgZmlsbCA9IHR5cGVfbWV0KSkgKwogIGdlb21fYmFyKHBvc2l0aW9uID0gIlN0YWNrIikgKyAgIyBOb3JtYWxpemUgdG8gcHJvcG9ydGlvbnMKICBjb29yZF9mbGlwKCkrCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gcGFsZXR0ZSkrCiAgbGFicygKICAgIHRpdGxlID0gIk1vc3QgUG9wdWxhciBNZWV0aW5nIFR5cGVzIGJ5IFBhcnR5IEFsaWdubWVudCIsCiAgICB4ID0gIlBvbGl0aWNhbCBBbGlnbm1lbnQiLAogICAgeSA9ICJDb3VudHMiLAogICAgZmlsbCA9ICJNZWV0aW5nIFR5cGUiCiAgKSArCiAgdGhlbWVfbWluaW1hbCgpKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpCgpncmFwaF81CmBgYAoKYGBge3J9CiMgTmV3IERGOiBDb3VudCBvY2N1cnJlbmNlcyBvZiBtZWV0aW5nIHR5cGVzIGZvciBlYWNoIGFsaWdubWVudApwYXJ0eV9wYWlyX2RmIDwtIGRmICU+JQogIGdyb3VwX2J5KHBhcnR5X3BhaXIsIHR5cGVfbWV0KSAlPiUKICBkcGx5cjo6c3VtbWFyaXNlKGNvdW50ID0gbigpLCAuZ3JvdXBzID0gImRyb3AiKQpgYGAKCioqQ2hhcnQgNjogQm94cGxvdCoqCgpgYGB7cn0KIyBDaGFydCA2OiBib3hwbG90IHNob3dpbmcgcGFydHkgYWxpZ25tZW50IG9uIGR1cmF0aW9uIG9mIHJlbGF0aW9uc2hpcHMgIAoKZ3JhcGhfNiA8LSBnZ3Bsb3QocGFydHlfcGFpcl9maWx0ZXJlZCwgYWVzKHggPSBwYXJ0eV9wYWlyLCB5ID0gZHVyYXRpb24sIGZpbGwgPSBwYXJ0eV9wYWlyKSkgKwogIGdlb21fYm94cGxvdCgpICsKICBjb29yZF9mbGlwKCkrCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiIzU2N2I4MSIsICIjNTY3YjgxIiwgIiM1NjdiODEiLCAiI2QzZDNkMyIsICIjZDNkM2QzIiwgIiNkM2QzZDMiLCAiI2FmNTI2NSIsICIjYWY1MjY1IiwgIiNhZjUyNjUiKSkrCiAgbGFicygKICAgIHRpdGxlID0gIlJlbGF0aW9uc2hpcCBEdXJhdGlvbiBieSBQb2xpdGljYWwgQWxpZ25tZW50IiwKICAgIHggPSBOVUxMLAogICAgeSA9ICJEdXJhdGlvbiBvZiBSZWxhdGlvbnNoaXAgKFllYXJzKSIsCiAgICBmaWxsID0gTlVMTAogICkrIAogIHRoZW1lX21pbmltYWwoKSsgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIikKCmdyYXBoXzYKCmBgYAoKKipEaXNjdXNzaW9uKio6CgpiKSAgV3JpdGUgYSBzaG9ydCBuYXJyYXRpdmUgKFx+MTUwIHdvcmRzKSBiYXNlZCBvbiB5b3VyIHZpc3VhbGl6YXRpb24sIGludGVncmF0aW5nIGRhdGEgaW5zaWdodHMgd2l0aCBhIGNvbXBlbGxpbmcgc3RvcnkuIFRoaXMgbmFycmF0aXZlIHNob3VsZCBiZSBzdWl0YWJsZSBmb3IgYSBmZWF0dXJlIGFydGljbGUsIGhpZ2hsaWdodGluZyBrZXkgZmluZGluZ3MgYW5kIHRoZWlyIGltcGxpY2F0aW9ucy4KCioqTmFycmF0aXZlKio6IFRoZSB3YXkgY291cGxlcyBtZWV0IGFuZCB0aGUgbG9uZ2V2aXR5IG9mIHRoZWlyIHJlbGF0aW9uc2hpcHMgc2VlbSBjbG9zZWx5IHRpZWQgdG8gcG9saXRpY2FsIGFsaWdubWVudC4gU29jaWFsIHNldHRpbmdzIGRvbWluYXRlIGFzIHRoZSBtb3N0IHBvcHVsYXIgbWVldGluZyB0eXBlIGZvciBwb2xpdGljYWxseSBhbGlnbmVkIGNvdXBsZXMsIHN1Y2ggYXMgIkRlbS1EZW0iIGFuZCAiUmVwLVJlcCwiIHdoaWxlIG1peGVkLWFmZmlsaWF0aW9uIGNvdXBsZXMgbGlrZSAiRGVtLUluZCIgc2hvdyBhIG1vcmUgZGl2ZXJzZSBkaXN0cmlidXRpb24gb2YgbWVldGluZyB0eXBlcywgaW5jbHVkaW5nIG9ubGluZSBwbGF0Zm9ybXMgYW5kIHdvcmstcmVsYXRlZCBhY3Rpdml0aWVzLiBUaGlzIHN1Z2dlc3RzIHRoYXQgc2hhcmVkIHBvbGl0aWNhbCBiZWxpZWZzIG1heSBzdHJlYW1saW5lIHNvY2lhbCBjaXJjbGVzLCBtYWtpbmcgaXQgZWFzaWVyIGZvciBsaWtlLW1pbmRlZCBpbmRpdmlkdWFscyB0byBjb25uZWN0LgoKV2hlbiBpdCBjb21lcyB0byByZWxhdGlvbnNoaXAgZHVyYXRpb24sIGNvdXBsZXMgd2l0aCB0aGUgc2FtZSBwb2xpdGljYWwgYWZmaWxpYXRpb24sIHBhcnRpY3VsYXJseSAiRGVtLURlbSIgYW5kICJSZXAtUmVwLCIgdGVuZCB0byBoYXZlIGxvbmdlci1sYXN0aW5nIHJlbGF0aW9uc2hpcHMgY29tcGFyZWQgdG8gbWl4ZWQtYWZmaWxpYXRpb24gcGFpcnMuIFRoaXMgcGF0dGVybiBoaW50cyBhdCB0aGUgc3RhYmlsaXppbmcgaW5mbHVlbmNlIG9mIHNoYXJlZCB2YWx1ZXMgYW5kIHdvcmxkdmlld3Mgb24gcGFydG5lcnNoaXBzLiBUaGVzZSBmaW5kaW5ncyBoaWdobGlnaHQgaG93IHBvbGl0aWNhbCBpZGVudGl0eSBleHRlbmRzIGJleW9uZCBpZGVvbG9neSwgaW5mbHVlbmNpbmcgYm90aCBob3cgY291cGxlcyBmb3JtIGFuZCBob3cgdGhleSBlbmR1cmUgb3ZlciB0aW1lLgoKIyMjIDQuIFlvdXIgVHVybiB0byBDaG9vc2UKClRoZXJlIGFyZSBsb3RzIG9mIG90aGVyIHZhcmlhYmxlcyB0aGF0IGNvdWxkIG1ha2UgZm9yIGFuIGludGVyZXN0aW5nIHN0b3J5LCBmb3IgZXhhbXBsZSwgZWR1Y2F0aW9uYWwgYmFja2dyb3VuZCBkaWZmZXJlbmNlcywgcmVsYXRpb25zaGlwIHN0YWdlcyAoRmlyc3QgTWV0LCBSb21hbnRpYywgTGl2ZSB0b2dldGhlciAmIE1hcnJpZWQpLCByZWdpb25hbCBwYXR0ZXJucywgcmVsYXRpb25zaGlwIGJyZWFrIHVwcywgc2V4dWFsIGJlaGF2aW9yIGV0Yy4gU2VsZWN0IHNvbWUgdmFyaWFibGVzIG9mIHlvdXIgY2hvaWNlIHRvIHRlbGwgYSBzdG9yeSB0aGF0IGNhcHR1cmVzIGFuIGludGVyZXN0aW5nIGluc2lnaHQgaW50byB0aGUgZGF0YS4KCkNyZWF0ZSBvbmUgKDEpIGNoYXJ0IGluIHRoaXMgc2VjdGlvbiB0byBoaWdobGlnaHQgc29tZSBpbXBvcnRhbnQgcGF0dGVybnMuIEJyaWVmbHkgZGlzY3VzcyB3aGljaCB2aXN1YWxpemF0aW9uIHlvdSByZWNvbW1lbmQgdG8geW91ciBlZGl0b3IsIHdoeSB5b3UgdGhpbmsgdGhlIHZpc3VhbGl6YXRpb24gaXMgdXNlZnVsLCBhbmQgd2hpY2ggcGF0dGVybnMgaXQgc2VydmVzIHRvIGhpZ2hsaWdodC4KCmBgYHtyfQojIHByb2JhYmlsaXR5IG9mIG1hcnJpYWdlIGFjcm9zcyBtZWV0aW5nIHR5cGVzIApkZl9zdGF0dXNfbWFyIDwtIGRmICU+JQogIGZpbHRlcihzaGlwX3N0YXR1cz09ICJtYXJyaWVkIikKCiMgU3VtbWFyaXplIGNvdW50cyBvZiBtZWV0aW5nIHR5cGVzIGZvciBtYXJyaWVkIHJlc3BvbmRlbnRzCnBpZV9tYXJfZGYgPC0gZGZfc3RhdHVzICU+JQogIGdyb3VwX2J5KHR5cGVfbWV0KSAlPiUKICBkcGx5cjo6c3VtbWFyaXNlKGNvdW50ID0gbigpLCAuZ3JvdXBzID0gImRyb3AiKQoKIyBQaWUgY2hhcnQ6IG1hcnJpYWdlIGFjcm9zcyBtZWV0aW5nIHR5cGVzIApncmFwaDcuMSA8LSBnZ3Bsb3QocGllX3NoaXBfZGYsIGFlcyh4ID0gIiIsIHkgPSBjb3VudCwgZmlsbCA9IHR5cGVfbWV0KSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCB3aWR0aCA9IDEsIGNvbG9yID0gIndoaXRlIikrICMgQ3JlYXRlIGJhcnMKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBwYWxldHRlKSsKICBjb29yZF9wb2xhcigieSIsIHN0YXJ0ID0gMCkrICMgVHJhbnNmb3JtIHRvIHBpZSBjaGFydAogICN0aGVtZV92b2lkKCkgKyAjIFJlbW92ZSBheGVzIGFuZCBncmlkcwogIGxhYnModGl0bGUgPSAiQ29tcGFyaW5nIE1lZXRpbmcgVHlwZXMgQmV0d2VlbiBNYXJyaWVkIGFuZCBEaXZvcmNlZC9TZXBhcmF0ZWQgUmVzcG9uZGVudHMiLAogICAgeSA9ICJNYXJyaWVkIiwgeD0icGVyY2VudCIsCiAgKSsKICB0aGVtZV9taW5pbWFsKCkrIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIpKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF9ibGFuaygpLAogICAgYXhpcy50aWNrcy54ID0gZWxlbWVudF9ibGFuaygpKQpgYGAKCmBgYHtyfQojIHByb2JhYmlsaXR5IG9mIGRpdm9yY2UsIHNlcGFyYXRpb24sIGJyZWFrdXAgYWNyb3NzIG1lZXRpbmcgdHlwZXMgCmRmX3N0YXR1c19kaXZfc2VwIDwtIGRmICU+JQogIGZpbHRlcihlbmRlZF9tYXI9PSAiZGl2b3JjZSIgfCBlbmRlZF9tYXIgPT0gInNlcGFyYXRpb24gd2l0aCBubyBkaXZvcmNlIiB8IGVuZGVkX25vbm1hciA9PSAiV2UgYnJva2UgdXAiKQoKIyBTdW1tYXJpemUgY291bnRzIG9mIG1lZXRpbmcgdHlwZXMgZm9yIG1hcnJpZWQgcmVzcG9uZGVudHMKcGllX25vbm1hcl9kZiA8LSBkZl9zdGF0dXNfZGl2X3NlcCAlPiUKICBncm91cF9ieSh0eXBlX21ldCkgJT4lCiAgZHBseXI6OnN1bW1hcmlzZShjb3VudCA9IG4oKSwgLmdyb3VwcyA9ICJkcm9wIikKCiMgUGllIGNoYXJ0OiBkaXZvcmNlL3NlcGFyYXRpb24gYWNyb3NzIG1lZXRpbmcgdHlwZXMgCmdyYXBoNy4yIDwtZ2dwbG90KHBpZV9ub25tYXJfZGYsIGFlcyh4ID0gIiIsIHkgPSBjb3VudCwgZmlsbCA9IHR5cGVfbWV0KSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCB3aWR0aCA9IDEsIGNvbG9yID0gIndoaXRlIikrIAogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IHBhbGV0dGUpKwogIGNvb3JkX3BvbGFyKCJ5Iiwgc3RhcnQgPSAwKSArICMgVHJhbnNmb3JtIHRvIHBpZSBjaGFydAogICN0aGVtZV92b2lkKCkgKyAjIFJlbW92ZSBheGVzIGFuZCBncmlkcwogIGxhYnMoCiAgICBmaWxsID0gTlVMTCwgeD0icGVyY2VudCIsCiAgICB5PSJEaXZvcmNlZC9TZXBhcmF0ZWQiCiAgKSsKICB0aGVtZV9taW5pbWFsKCkrIAogIHRoZW1lKAogICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X2JsYW5rKCksICAgIyBSZW1vdmUgeC1heGlzIHRleHQKICAgIGF4aXMudGlja3MueCA9IGVsZW1lbnRfYmxhbmsoKSwgICMgUmVtb3ZlIHgtYXhpcyB0aWNrcwogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgc2l6ZSA9IDE0KSwgIyBDZW50ZXIgYW5kIGFkanVzdCB0aXRsZSBzaXplCiAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIKICApCgpncmFwaF83X2NvbWIgPC0gZ3JhcGg3LjEgKyBncmFwaDcuMgpncmFwaF83IDwtIGdyYXBoXzdfY29tYiArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0icmlnaHQiKQpncmFwaF83CmBgYAoKKipEaXNjdXNzaW9uKio6IFRoZSBkdWFsIHBpZSBjaGFydCBlZmZlY3RpdmVseSBjb21wYXJlcyBob3cgbWVldGluZyB0eXBlcyBkaWZmZXIgYmV0d2VlbiBtYXJyaWVkIGFuZCBkaXZvcmNlZC9zZXBhcmF0ZWQgcmVzcG9uZGVudHMuIEl0IGhpZ2hsaWdodHMgdGhhdCBzb2NpYWwgc2V0dGluZ3MgYXJlIHByb21pbmVudCBmb3IgYm90aCBncm91cHMsIHdoaWxlIHdvcmstcmVsYXRlZCBhY3Rpdml0aWVzIGFyZSBtb3JlIGNvbW1vbiBhbW9uZyBtYXJyaWVkIGNvdXBsZXMuIFRoZSB1c2Ugb2YgcGVyY2VudGFnZXMgd2l0aGluIGVhY2ggc2xpY2UgKG9ic2VydmluZyB0aGUgdHdvIGludGVyYWN0aXZlIHBsb3RzKSB3b3VsZCBtYWtlIHRoZSBjb21wYXJpc29uIGV2ZW4gY2xlYXJlciwgYWxsb3dpbmcgcmVhZGVycyB0byBlYXNpbHkgZ3Jhc3AgdGhlIHJlbGF0aXZlIGltcG9ydGFuY2Ugb2YgZWFjaCBtZWV0aW5nIHR5cGUuCgojIyBJbnRlcmFjdGl2aXR5CgojIyMgNS4gTWFrZSBUd28gUGxvdHMgSW50ZXJhY3RpdmUKCmEpICBDaG9vc2UgMiBvZiB0aGUgcGxvdHMgeW91IGNyZWF0ZWQgYWJvdmUgYW5kIGFkZCBpbnRlcmFjdGl2aXR5LiBGb3IgYXQgbGVhc3Qgb25lIG9mIHRoZXNlIGludGVyYWN0aXZlIHBsb3RzLCB0aGlzIHNob3VsZCBub3QgYmUgZG9uZSB0aHJvdWdoIHRoZSB1c2Ugb2YgYGdncGxvdGx5YAoKKipJbnRlcmFjdGl2ZSBQbG90IDE6IHBsb3RseSBwaWVjaGFydCB2ZXJzaW9uKioKYGBge3J9CmxpYnJhcnkocGxvdGx5KQoKIyBDcmVhdGUgaW50ZXJhY3RpdmUgcGllIGNoYXJ0CmludGVyYWN0aXZlX3BpZV9tYXIgPC0gcGxvdF9seSgKICBkYXRhID0gcGllX21hcl9kZiwKICBsYWJlbHMgPSB+dHlwZV9tZXQsICAgICMgTWVldGluZyB0eXBlcyBhcyBsYWJlbHMKICB2YWx1ZXMgPSB+Y291bnQsICAgICAgICMgQ291bnRzIGFzIHZhbHVlcwogIHR5cGUgPSAncGllJywgICAgICAgICAgIyBTcGVjaWZ5IHBpZSBjaGFydAogIHRleHRpbmZvID0gJ2xhYmVsK3BlcmNlbnQnLCAjIFNob3cgbGFiZWxzIGFuZCBwZXJjZW50YWdlcwogIGhvdmVyaW5mbyA9ICdsYWJlbCt2YWx1ZStwZXJjZW50JywgIyBIb3ZlciBpbmZvOiBsYWJlbCwgdmFsdWUsIHBlcmNlbnRhZ2UKICBtYXJrZXIgPSBsaXN0KGNvbG9ycyA9IHBhbGV0dGUpICMgQ3VzdG9tIGNvbG9ycwopICU+JQogIGxheW91dCgKICAgIHRpdGxlID0gIkRpc3RyaWJ1dGlvbiBvZiBNZWV0aW5nIFR5cGVzIEFtb25nIE1hcnJpZWQgUmVzcG9uZGVudHMiLAogICAgbGVnZW5kID0gbGlzdChvcmllbnRhdGlvbiA9ICJoIikgIyBIb3Jpem9udGFsIGxlZ2VuZAogICkKaW50ZXJhY3RpdmVfcGllX21hcgoKIyBDcmVhdGUgaW50ZXJhY3RpdmUgcGllIGNoYXJ0CmludGVyYWN0aXZlX3BpZV9kaXZzZXAgPC0gcGxvdF9seSgKICBkYXRhID0gcGllX25vbm1hcl9kZiwKICBsYWJlbHMgPSB+dHlwZV9tZXQsICAgICMgTWVldGluZyB0eXBlcyBhcyBsYWJlbHMKICB2YWx1ZXMgPSB+Y291bnQsICAgICAgICMgQ291bnRzIGFzIHZhbHVlcwogIHR5cGUgPSAncGllJywgICAgICAgICAgIyBTcGVjaWZ5IHBpZSBjaGFydAogIHRleHRpbmZvID0gJ2xhYmVsK3BlcmNlbnQnLCAjIFNob3cgbGFiZWxzIGFuZCBwZXJjZW50YWdlcwogIGhvdmVyaW5mbyA9ICdsYWJlbCt2YWx1ZStwZXJjZW50JywgIyBIb3ZlciBpbmZvOiBsYWJlbCwgdmFsdWUsIHBlcmNlbnRhZ2UKICBtYXJrZXIgPSBsaXN0KGNvbG9ycyA9IHBhbGV0dGUpICMgQ3VzdG9tIGNvbG9ycwopICU+JQogIGxheW91dCgKICAgIHRpdGxlID0gIkRpc3RyaWJ1dGlvbiBvZiBNZWV0aW5nIFR5cGVzIEFtb25nIE1hcnJpZWQgUmVzcG9uZGVudHMiLAogICAgbGVnZW5kID0gbGlzdChvcmllbnRhdGlvbiA9ICJoIikgIyBIb3Jpem9udGFsIGxlZ2VuZAogICkKaW50ZXJhY3RpdmVfcGllX2RpdnNlcApgYGAKCmBgYHtyfQojIEludGVyYWN0aXZlIFBsb3QgMjoKCmdncGxvdGx5KGdyYXBoXzMpCgpgYGAKCioqSW50ZXJhY3RpdmUgUGxvdCAyOioqCgpiKSAgQnJpZWZseSBkZXNjcmliZSB0byB0aGUgZWRpdG9yIHdoeSBpbnRlcmFjdGl2aXR5IGluIHRoZXNlIHZpc3VhbGl6YXRpb25zIGlzIHBhcnRpY3VsYXJseSBoZWxwZnVsIGZvciBhIHJlYWRlciwgcmVmZXJlbmNpbmcgdXNlciBlbmdhZ2VtZW50IHRoZW9yaWVzIG9yIGludGVyYWN0aW9uIGRlc2lnbiBwcmluY2lwbGVzLgoKKipEZXNjcmliZSoqOiBJbnRlcmFjdGl2aXR5IGluIHRoZXNlIHZpc3VhbGl6YXRpb25zIGFsbG93cyByZWFkZXJzIHRvIGV4cGxvcmUgdGhlIGRhdGEgaW4gYSBtb3JlIGVuZ2FnaW5nIGFuZCBpbnR1aXRpdmUgd2F5LiBGb3IgZXhhbXBsZSwgaG92ZXJpbmcgb3ZlciB0aGUgcGllIGNoYXJ0IHNsaWNlcyByZXZlYWxzIGV4YWN0IHBlcmNlbnRhZ2VzIGFuZCBtZWV0aW5nIHR5cGVzLCBtYWtpbmcgaXQgZWFzaWVyIHRvIGNvbXBhcmUgaG93IG1hcnJpZWQgYW5kIGRpdm9yY2VkL3NlcGFyYXRlZCBjb3VwbGVzIG1ldC4gU2ltaWxhcmx5LCB0aGUgbGluZSBncmFwaCBlbmFibGVzIHJlYWRlcnMgdG8gZm9jdXMgb24gc3BlY2lmaWMgdHJlbmRzLCBzdWNoIGFzIHRoZSBzaGFycCByaXNlIG9mIG9ubGluZSBtZWV0aW5nIHBsYXRmb3JtcyBhZnRlciAyMDAwLiBUaGVzZSBmZWF0dXJlcyBtYWtlIHRoZSBkYXRhIG1vcmUgYWNjZXNzaWJsZSBhbmQgZW5jb3VyYWdlIHJlYWRlcnMgdG8gdW5jb3ZlciBpbnNpZ2h0cyBvbiB0aGVpciBvd24uCgojIyMgNi4gRGF0YSBUYWJsZQoKVG8gYWxsb3cgdGhlIHJlYWRlciB0byBleHBsb3JlIHRoZSBzdXJ2ZXkgZGF0YSBieSB0aGVtc2VsdmVzIGEgYml0LCBzZWxlY3QgYSBmZXcgdXNlZnVsIHZhcmlhYmxlcywgcmVuYW1lIHRoZW0gYXBwcm9wcmlhdGVseSBmb3IgdGhlIHRhYmxlIHRvIGJlIHNlbGYtZXhwbGFuYXRvcnksIGFuZCBhZGQgYW4gaW50ZXJhY3RpdmUgZGF0YSB0YWJsZSB0byB0aGUgb3V0cHV0LiBNYWtlIHN1cmUgdGhlIGNvbHVtbnMgYXJlIGNsZWFybHkgbGFiZWxlZC4gU2VsZWN0IHRoZSBhcHByb3ByaWF0ZSBvcHRpb25zIGZvciB0aGUgZGF0YSB0YWJsZSAoZS5nLiBzZWFyY2ggYmFyLCBzb3J0aW5nLCBjb2x1bW4gZmlsdGVycywgaW4tbGluZSB2aXN1YWxpemF0aW9ucyBldGMuIC0tIGFzIGZhciBhcyB0aGUgdG9vbHMgc3VwcGxpZWQgaW4gbGVjdHVyZSBhbGxvdykuCgpgYGB7cn0KIyBJbnRlcmFjdGl2ZSB0YWJsZToKbGlicmFyeShEVCkKCiMgU2VsZWN0IGFuZCByZW5hbWUgcmVsZXZhbnQgY29sdW1ucwppbnRlcmFjdGl2ZV90YWIgPC0gZGYgJT4lCiAgc2VsZWN0KAogICAgdHlwZV9tZXQsIAogICAgc2hpcF9zdGF0dXMsIAogICAgZHVyYXRpb24sCiAgICByZXNwX2dlbmRlciwKICAgIHJlc3BfcGFydHksIAogICAgcGFydF9wYXJ0eQogICkgJT4lCiAgcmVuYW1lKAogICAgYE1lZXRpbmcgVHlwZWAgPSB0eXBlX21ldCwKICAgIGBSZWxhdGlvbnNoaXAgU3RhdHVzYCA9IHNoaXBfc3RhdHVzLAogICAgYExlbmd0aCBvZiBSZWxhdGlvbnNoaXAgKFllYXJzKWAgPSBkdXJhdGlvbiwKICAgIGBSZXNwb25kZW50J3MgR2VuZGVyYCA9IHJlc3BfZ2VuZGVyLAogICAgYFJlc3BvbmRlbnQncyBQb2xpdGljYWwgQWZmaWxpYXRpb25gID0gcmVzcF9wYXJ0eSwKICAgIGBQYXJ0bmVyJ3MgUG9saXRpY2FsIEFmZmlsaWF0aW9uYCA9IHBhcnRfcGFydHkKICApCgojIENyZWF0ZSB0aGUgaW50ZXJhY3RpdmUgZGF0YSB0YWJsZQpkYXRhdGFibGUoCiAgaW50ZXJhY3RpdmVfdGFiLAogIGNsYXNzID0gImNlbGwtYm9yZGVyIHN0cmlwZSBob3ZlciBjb21wYWN0IiwgICMgU3R5bGluZyBvcHRpb25zCiAgZmlsdGVyID0gInRvcCIsICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBBZGQgY29sdW1uIGZpbHRlcnMgYXQgdGhlIHRvcAogIG9wdGlvbnMgPSBsaXN0KAogICAgcGFnZUxlbmd0aCA9IDEwLCAgICAgICAgICAgICAgICAgICAgICAgICAgICMgTnVtYmVyIG9mIHJvd3MgcGVyIHBhZ2UKICAgIGF1dG9XaWR0aCA9IFRSVUUsICAgICAgICAgICAgICAgICAgICAgICAgICAjIEF1dG9tYXRpY2FsbHkgYWRqdXN0IGNvbHVtbiB3aWR0aHMKICAgIGRvbSA9ICdCZnJ0aXAnLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIEFkZCBidXR0b25zIGZvciBleHBvcnQvZG93bmxvYWQKICAgIGJ1dHRvbnMgPSBjKCdjb3B5JywgJ2NzdicsICdleGNlbCcpICAgICAgICAjIEV4cG9ydCBvcHRpb25zCiAgKSwKICBjYXB0aW9uID0gIkV4cGxvcmUgTWVldGluZyBUeXBlcyBhbmQgUmVsYXRpb25zaGlwIERldGFpbHMgb2YgU3VydmV5IFJlc3BvbmRlbnRzIgopCgoKYGBgCgojIyBUZWNobmljYWwgRGV0YWlscwoKVGhlIGRhdGEgY29tZXMgaW4gYSByZWFzb25hYmx5IGNsZWFuIGZpbGUuIEhvd2V2ZXIsIGlmIHlvdSBkbyBmaW5kIGlzc3VlcyB3aXRoIHRoZSBkYXRhLCByZWNvZGUgYW55IHZhbHVlcywgZXRjLiBwbGVhc2UgbWFrZSB0aGlzIGNsZWFyIGluIHRoZSBjb2RlIChhbmQgaWYgc2lnbmlmaWNhbnQgYWRkIGludG8gdGhlIGRlc2NyaXB0aW9uKS4KCklmIG5lZWRlZCBmb3IgeW91ciB2aXN1YWxpemF0aW9uLCB5b3UgY2FuIGFkZCB2aXN1YWwgZHJhcGVyeSBsaWtlIGljb25zLCBpbWFnZXMgZXRjLiBidXQgeW91IGFyZSBjZXJ0YWlubHkgbm90IG9ibGlnYXRlZCB0byBkbyB0aGF0LiBXaGF0IGlzIGltcG9ydGFudCwgaG93ZXZlciwgdG8gKnVzZSBhIGNvbnNpc3RlbnQgc3R5bGUgYWNyb3NzIGFsbCB5b3VyIHZpc3VhbGl6YXRpb25zKi4KClBhcnQgb2YgdGhlIHRhc2sgd2lsbCBiZSB0cmFuc2Zvcm1pbmcgdGhlIGRhdGFzZXQgaW50byBhIHNoYXBlIHRoYXQgYWxsb3dzIHlvdSB0byBwbG90IHdoYXQgeW91IHdhbnQuIEZvciBzb21lIHBsb3RzLCB5b3Ugd2lsbCBuZWNlc3NhcmlseSBuZWVkIHRvIGJlIHNlbGVjdGl2ZSBpbiB3aGF0IHRvIGluY2x1ZGUgYW5kIHdoYXQgdG8gbGVhdmUgb3V0LgoKTWFrZSBzdXJlIHRvIHVzZSAqYXQgbGVhc3QqIHRocmVlIGRpZmZlcmVudCB0eXBlcyBvZiBncmFwaHMsIGUuZy4gbGluZSBncmFwaHMsIHNjYXR0ZXIsIGhpc3RvZ3JhbXMsIGJhciBjaGFydHMsIGRvdCBwbG90cywgaGVhdCBtYXBzLCBldGMuCgojIyBTdWJtaXNzaW9uCgpQbGVhc2UgZm9sbG93IHRoZSBbaW5zdHJ1Y3Rpb25zXSgvRXhlcmNpc2VzL2hvbWV3b3JrX3N1Ym1pc3Npb25faW5zdHJ1Y3Rpb25zLm1kKSB0byBzdWJtaXQgeW91ciBob21ld29yay4gVGhlIGhvbWV3b3JrIGlzIGR1ZSBvbiBGcmlkYXksIEZlYnJ1YXJ5IDIxIGF0IDVwbS4KCiMjIFBsZWFzZSBTdGF5IEhvbmVzdCEKClllcywgdGhpcyB0eXBlIG9mIGRhdGEgaGFzIGJlZW4gYW5hbHl6ZWQgYmVmb3JlLiBJZiB5b3UgZG8gY29tZSBhY3Jvc3Mgc29tZXRoaW5nLCBwbGVhc2Ugbm8gd2hvbGVzYWxlIGNvcHlpbmcgb2Ygb3RoZXIgaWRlYXMuIFdlIGFyZSB0cnlpbmcgdG8gZXZhbHVhdGUgeW91ciBhYmlsaXRpZXMgaW4gdXNpbmcgdGhlIHBhY2thZ2VzIHdlIGRpc2N1c3NlZCB0byBjcmVhdGUgZGF0YSB2aXN1YWxpemF0aW9uIG5vdCB0aGUgYWJpbGl0eSB0byBkbyBpbnRlcm5ldCBzZWFyY2hlcy4gU2ltaWxhcmx5LCBwbGVhc2Ugc3RheSBhd2F5IGZyb20gc29sdXRpb25zIC8gY29kZSBjcmVhdGVkIGJ5IGdlbmVyYXRpdmUgQUkuIEhlcmUgaXMgeW91ciBjaGFuY2UgdG8gbGVhcm4gYW5kIGFwcGx5IHRoZSBjb25jZXB0cyB3ZSBoYXZlIGRpc2N1c3NlZCBpbiBjbGFzcyEKCkFsc28sIHRoaXMgaXMgYW4gaW5kaXZpZHVhbGx5IGFzc2lnbmVkIGV4ZXJjaXNlIC0tIHBsZWFzZSBrZWVwIHlvdXIgc29sdXRpb24gdG8geW91cnNlbGYhCg==